#region File Description
//-----------------------------------------------------------------------------
// MessageBoxScreen.cs
//
// Microsoft XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#endregion

#region Using Statements
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input.Touch;
#endregion

namespace IcyTowerMobile
{
	/// <summary>
	/// A popup message box screen, used to display "are you sure?"
	/// confirmation messages.
	/// </summary>
	class MessageBoxScreen : GameScreen
	{
		#region Fields

		private string message;
		private Texture2D backgroundTexture;
		private MessageBoxButton acceptButton;
		private MessageBoxButton cancelButton;

		private bool showNegativeButton;
		private string positiveButtonText;
		private string negativeButtonText;

		private SpriteFont font;
		private Vector2 textSize;
		private Vector2 textPosition;

		#endregion

		#region Events

		public event EventHandler<PlayerIndexEventArgs> Accepted;
		public event EventHandler<PlayerIndexEventArgs> Cancelled;

		#endregion

		#region Initialization


		/// <summary>
		/// Constructor for initializing a message box with no negative button,
		/// but just an "OK" confirmation button.
		/// </summary>
		public MessageBoxScreen(string message)
			: this(message, "OK", null)
		{
		}


		/// <summary>
		/// Constructor for initializing a message box with specified positive and negative button text.
		/// </summary>
		public MessageBoxScreen(string message, string positiveButtonText, string negativeButtonText)
		{
			this.showNegativeButton = negativeButtonText != null;
			this.message = message;
			this.positiveButtonText = positiveButtonText;
			this.negativeButtonText = negativeButtonText;

			IsPopup = true;

			TransitionOnTime = TimeSpan.FromSeconds(0.2);
			TransitionOffTime = TimeSpan.FromSeconds(0.2);

			acceptButton = new MessageBoxButton();
			if (showNegativeButton)
				cancelButton = new MessageBoxButton();
		}


		/// <summary>
		/// Loads graphics content for this screen. This uses the shared ContentManager
		/// provided by the Game class, so the content will remain loaded forever.
		/// Whenever a subsequent MessageBoxScreen tries to load this same content,
		/// it will just get back another reference to the already loaded data.
		/// </summary>
		public override void LoadContent()
		{
			ContentManager content = ScreenManager.Game.Content;

			// load textures
			backgroundTexture = content.Load<Texture2D>("textures/texture_message_box");
			Texture2D buttonTexture = content.Load<Texture2D>("textures/texture_message_box_button");
			Texture2D buttonPressedTexture = content.Load<Texture2D>("textures/texture_message_box_button_pressed");

			// center the message text in the viewport
			font = ScreenManager.MenuFont;
			Viewport viewport = ScreenManager.GraphicsDevice.Viewport;
			Vector2 viewportSize = new Vector2(viewport.Width, viewport.Height);
			textSize = font.MeasureString(message);
			textPosition = (viewportSize - textSize) / 2;

			// position the buttons below the message
			int vpad = 50;
			int hpad = 20;
			if (showNegativeButton)
			{
				// center both buttons
				acceptButton.Initialize(buttonTexture, buttonPressedTexture, vpad, (int)(textPosition.Y + textSize.Y + hpad), positiveButtonText);
				cancelButton.Initialize(buttonTexture, buttonPressedTexture, viewport.Width - buttonTexture.Width - vpad, (int)(textPosition.Y + textSize.Y + hpad), negativeButtonText);
			}
			else
			{
				// center just positive button
				acceptButton.Initialize(buttonTexture, buttonPressedTexture, (viewport.Width - buttonTexture.Width) / 2, (int)(textPosition.Y + textSize.Y + hpad), positiveButtonText);
			}

		}


		#endregion

		#region Handle Input

		public override void Update(GameTime gameTime, bool otherScreenHasFocus,
													  bool coveredByOtherScreen)
		{
			base.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen);

			TouchCollection touches = TouchPanel.GetState();

			if (touches.Count > 0)
			{
				foreach (TouchLocation item in touches)
				{
					// user has pressed somewhere on the screen
					acceptButton.Update(gameTime, item.Position);
					if (showNegativeButton)
						cancelButton.Update(gameTime, item.Position);
					if (acceptButton.Contains(item.Position))
					{
						// user has pressed positive button
						triggerAccepted(new PlayerIndex());
					}
					else if (showNegativeButton && cancelButton.Contains(item.Position))
					{
						// user has pressed negative button
						triggerCancelled(new PlayerIndex());
					}
				}
			}
		}


		/// <summary>
		/// Responds to user input, accepting or cancelling the message box.
		/// </summary>
		public override void HandleInput(InputState input)
		{
			PlayerIndex playerIndex;

			// We pass in our ControllingPlayer, which may either be null (to
			// accept input from any player) or a specific index. If we pass a null
			// controlling player, the InputState helper returns to us which player
			// actually provided the input. We pass that through to our Accepted and
			// Cancelled events, so they can tell which player triggered them.
			if (input.IsMenuSelect(ControllingPlayer, out playerIndex))
			{
				triggerAccepted(playerIndex);
			}
			else if (input.IsMenuCancel(ControllingPlayer, out playerIndex))
			{
				triggerCancelled(playerIndex);
			}
		}

		private void triggerAccepted(PlayerIndex playerIndex)
		{
			// Raise the accepted event, then exit the message box.
			if (Accepted != null)
				Accepted(this, new PlayerIndexEventArgs(playerIndex));

			ExitScreen();
		}

		private void triggerCancelled(PlayerIndex playerIndex)
		{
			// Raise the cancelled event, then exit the message box.
			if (Cancelled != null)
				Cancelled(this, new PlayerIndexEventArgs(playerIndex));

			ExitScreen();
		}


		#endregion

		#region Draw


		/// <summary>
		/// Draws the message box.
		/// </summary>
		public override void Draw(GameTime gameTime)
		{
			SpriteBatch spriteBatch = ScreenManager.SpriteBatch;

			// Darken down any other screens that were drawn beneath the popup.
			ScreenManager.FadeBackBufferToBlack(TransitionAlpha * 2 / 3);

			// The background includes a border somewhat larger than the text itself.
			const int hPad = 32;
			const int vPad = 16;

			Rectangle backgroundRectangle = new Rectangle((int)textPosition.X - hPad,
														  (int)textPosition.Y - vPad,
														  (int)textSize.X + hPad * 2,
														  (int)textSize.Y + acceptButton.Height + vPad * 4);

			// Fade the popup alpha during transitions.
			Color color = Color.White * TransitionAlpha;

			spriteBatch.Begin();

			// Draw the background rectangle.
			spriteBatch.Draw(backgroundTexture, backgroundRectangle, color);

			// Draw the message box text.
			spriteBatch.DrawString(font, message, textPosition, Color.Black);

			// Draw the buttons.
			acceptButton.Draw(spriteBatch, font, color);
			if (showNegativeButton)
				cancelButton.Draw(spriteBatch, font, color);

			spriteBatch.End();
		}


		#endregion
	}
}
